<?php
// +----------------------------------------------------------------------
// | Copyright (c) 2020 All rights reserved.
// +----------------------------------------------------------------------
// | User: Simony <1362229026@qq.com>
// | wechat: Shen86579595
// +----------------------------------------------------------------------

namespace app\common\logic;

use OSS\OssClient;
use OSS\Core\OssException;

class wxTradePayLogic
{

    private $appid; //应用ID
    private $mch_id; //商户号
    private $notify_url;
    private $key; //key为商户平台设置的密钥key

    public function __construct()
    {
        $weChatPay = sysConfig('wechat_pay');
        $this->appid = isset($weChatPay['appid']) ? $weChatPay['appid'] : '';
        $this->mch_id = isset($weChatPay['mch_id']) ? $weChatPay['mch_id'] : '';
        $this->notify_url = isset($weChatPay['notify_url']) ? $weChatPay['notify_url'] : '';
        $this->key = isset($weChatPay['key']) ? $weChatPay['key'] : '';
    }

    /**
     * User: Simony
     * Function:创建订单
     * @param $out_trade_no
     * @param $name
     * @param $price
     * @param $attach
     * @return array
     */
    public function wxTradePay($out_trade_no, $name, $price, $attach)
    {
        $nonce_str = $this->rand_code();
        $data = [
            'appid' => $this->appid,
            'mch_id' => $this->mch_id,
            'attach' => $attach,
            'nonce_str' => $this->rand_code(), //随机字符串
            'body' => $name, //商品描述
            'spbill_create_ip' => $this->appid, //ip地址
            'total_fee' => $price * 100,  //总金额
            'out_trade_no' => $out_trade_no, //商户订单号
            'notify_url' => $this->notify_url,
            'trade_type' => 'APP',
        ];
        $data['sign'] = $this->getSign($data);  //获取签名
        $xml = $this->ToXml($data);            //数组转xml
        //curl 传递给微信方
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        $data = $this->postXmlCurl($xml, $url);
        if ($data['code'] != SUCCESS) return ds_arr($data['code'], $data['msg'], $data['result']);

        $res = $this->FromXml($data['result']);
        if ($res['return_code'] != 'SUCCESS') return ds_arr(ERROR, '签名失败');

        //接收微信返回的数据,传给APP!
        $arr = [
            'prepayid' => $res['prepay_id'],
            'appid' => $res['appid'],
            'partnerid' => $res['partnerid'],
            'package' => 'Sign=WXPay',
            'noncestr' => $nonce_str,
            'timestamp' => time(),
        ];
        //第二次生成签名
        $sign = $this->getSign($arr);
        $arr['sign'] = $sign;
        return ds_arr(SUCCESS, '签名成功', $arr);
    }


    /**
     * User: Simony
     * Function:
     * @param $xml
     * @param $url
     * @return array
     */
    public function postXmlCurl($xml, $url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        if (stripos($url, "https://") !== FALSE) {
            curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        } else {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);//严格校验
        }
        //设置header
        curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        curl_setopt($ch, CURLOPT_POST, TRUE);
        //传输文件
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        $ssr = array();
        if (!$data) {
            $error = curl_errno($ch);
            curl_close($ch);
            return ds_arr(ERROR, 'curl出错，错误码:' . $error);
        }
        curl_close($ch);
        return ds_arr(SUCCESS, '获取成功', $data);
    }

    /**
     * User: Simony
     * Function:随机字符串
     * @return bool|string
     */
    public function rand_code()
    {
        $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';//62个字符
        $str = str_shuffle($str);
        $str = substr($str, 0, 32);
        return $str;
    }

    /**
     * User: Simony
     * Function:生成签名
     * @param $params
     * @return string
     */
    public function getSign($params)
    {
        ksort($params);
        foreach ($params as $key => $item) {
            if (!empty($item)) $newArr[] = $key . '=' . $item;
        }
        $stringA = implode("&", $newArr);
        $stringSignTemp = $stringA . "&key=" . $this->key;
        $stringSignTemp = MD5($stringSignTemp);
        $sign = strtoupper($stringSignTemp);
        return $sign;
    }

    /********************************* simony  xml 处理  start ****************************************************************/
    public function ToXml($data = array())
    {
        if (!is_array($data) || count($data) <= 0) {
            return '数组异常';
        }
        $xml = "<xml>";
        foreach ($data as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    public function FromXml($xml)
    {
        if (!$xml) {
            echo "xml数据异常！";
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    /********************************* simony  xml 处理  end ****************************************************************/


    /**
     * User: Simony
     * Function: 回调
     */
//    public function wxNotify()
//    {
//        //接收微信返回的数据数据,返回的xml格式
//        $xmlData = file_get_contents('php://input');
//        //将xml格式转换为数组
//        $data = $this->FromXml($xmlData);
//        $arr = array();
//        //为了防止假数据，验证签名是否和返回的一样。
//        //记录一下，返回回来的签名，生成签名的时候，必须剔除sign字段。
//        $sign = $data['sign'];
//        unset($data['sign']);
//        if ($sign == $this->getSign($data)) {
//            //签名验证成功后，判断返回微信返回的
//            if ($data['result_code'] == 'SUCCESS'  && $data['return_code'] == "SUCCESS") {
//                //根据返回的订单号做业务逻辑
//                $flow = new model\Flow();
//                $flow->order_paid($data['out_trade_no'], $data['transaction_id']);
//                //处理完成之后，告诉微信成功结果！
//                echo '<xml>
//						<return_code><![CDATA[SUCCESS]]></return_code>
//						<return_msg><![CDATA[OK]]></return_msg>
//						</xml>';
//                exit();
//            } else {
//                $file = fopen('./log.txt', 'a+');
//                fwrite($file, "错误信息：" . $data['return_msg'] . date("Y-m-d H:i:s"), time() . "\r\n");
//            }
//        } else {
//            $file = fopen('./log.txt', 'a+');
//            fwrite($file, "错误信息：签名验证失败" . date("Y-m-d H:i:s"), time() . "\r\n");
//        }
//    }

}